package com.cssl.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.cssl.domain.DtsUser;
import com.cssl.domain.DtsUserAccount;
import com.cssl.domain.dto.UsersDto;
import com.cssl.domain.dto.WeiXinLoginByPhoneDto;
import com.cssl.domain.dto.WeiXinLoginDto;
import com.cssl.domain.dto.WeiXinRegistryByPhoneDto;
import com.cssl.domain.vo.DtsUserVO;
import com.cssl.mapper.DtsUserAccountMapper;
import com.cssl.mapper.DtsUserMapper;
import com.cssl.service.DtsUserService;
import com.cssl.util.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class DtsUserServiceImpl implements DtsUserService {
    @Autowired
    private StringRedisTemplate template;
    @Autowired
    private DtsUserMapper mapper;
    @Autowired
    private DtsUserAccountMapper dtsUserAccountMapper;
    @Autowired
    private SendMess sendMess;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public Result sendMobileMess(String phone) {
        String value = String.valueOf(RandomUtil.randomInt(1000, 10000));
        sendMess.send(phone, value);
        //将手机号当作键,验证码为值 (5分钟过期)
        template.opsForValue().set(StorageVariable.PHONE_MESS + phone, value, 5, TimeUnit.MINUTES);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, value, System.currentTimeMillis());
    }

    /**
     * 老模板接口1
     *
     * @param dto
     * @param request
     * @return
     */
    @Override
    public Result WeiXinLoginByPhone(WeiXinLoginByPhoneDto dto, HttpServletRequest request) {
        //验证验证码是否正确
        String redisCode = template.opsForValue().get(StorageVariable.PHONE_MESS + dto.getPhone());
        if (StrUtil.isEmpty(redisCode)) {
            //为空
            return Result.fail(InfoCode.UNPROCESSABLE_ENTITY, InfoCode.MESSAGE_UNPROCESSABLE_ENTITY, System.currentTimeMillis());
        }
        //比较验证码是否一致
        if (!dto.getPhoneYzm().equals(redisCode)) {
            //验证码不一致
            return Result.fail(InfoCode.UNPROCESSABLE_ENTITY, InfoCode.MESSAGE_UNPROCESSABLE_ENTITY, System.currentTimeMillis());
        }
        //一致,判断用户是否存在
        DtsUser user = mapper.findUserByPhone(dto.getPhone());
        int flag = 0;
        if (ObjectUtil.isEmpty(user)) {
            //为空(注册)
            user = new DtsUser();
            user.setMobile(dto.getPhone());
            user.setUserName(dto.getUserName());

            String randomStr = RandomUtil.randomString(5);
            user.setNickName(StorageVariable.USER_NAME_PROXY + randomStr + dto.getUserName());
            //密码暂时用用户手机号后4位
            String password = dto.getPhone().substring(dto.getPhone().length() - 4);
            user.setPassword(MD5Util.string2MD5(password));
            user.setGender(0);
            user.setLastLoginTime(new Date());
            user.setLastLoginIp(CommonUtil.getIpAddr(request));
            user.setUserLevel(0);
            user.setAvatar(dto.getAvatarUrl());
            user.setStatus(0);
            user.setAddTime(new Date());
            user.setDeleted(0);
            //获得微信Openid
            WeiXinSubmitUtil weiXinSubmitController = new WeiXinSubmitUtil();
            Map map = weiXinSubmitController.decodeUserInfo(dto.getCode());

            String openid = map.get("openid").toString();
            user.setWeiXinOpenId(openid);
            flag = mapper.addUser(user);
        }
        if (flag <= 0) {
            //新增失败
            return Result.fail(InfoCode.FAILED, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        //查询再加id
        DtsUser phone = mapper.findUserByPhone(dto.getPhone());
        StpKit.USER.login(phone.getId());
        SaTokenInfo tokenInfo = StpKit.USER.getTokenInfo();

        Map map = new HashMap();
        map.put("saToken", tokenInfo);
        map.put("flag", true);
        //成功
        return Result.result(InfoCode.CREATED, InfoCode.MESSAGE_CREATED, map, System.currentTimeMillis());
    }

    /**
     * 新模板接口
     *
     * @param dto
     * @param request
     * @return
     */
    @Override
    public Result weiXinRegisterByPhone(WeiXinRegistryByPhoneDto dto, HttpServletRequest request) {
        DtsUser user = mapper.getUserByPhone(dto.getPhone());
        if (user != null) {
            return Result.fail(InfoCode.FAILED, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        String redisCode = template.opsForValue().get(StorageVariable.PHONE_MESS + dto.getPhone());
        if (StrUtil.isEmpty(redisCode)) {
            //为空
            return Result.fail(InfoCode.UNPROCESSABLE_ENTITY, InfoCode.MESSAGE_UNPROCESSABLE_ENTITY, System.currentTimeMillis());
        }
        //比较验证码是否一致
        if (!dto.getYzm().equals(redisCode)) {
            //验证码不一致
            return Result.fail(InfoCode.UNPROCESSABLE_ENTITY, InfoCode.MESSAGE_UNPROCESSABLE_ENTITY, System.currentTimeMillis());
        }
        //注册
        DtsUser newUser = new DtsUser();
        newUser.setUserName(dto.getUserName());
        String randomStr = RandomUtil.randomString(5);
        newUser.setNickName(StorageVariable.USER_NAME_PROXY + randomStr + dto.getUserName());
        newUser.setUpdateTime(new Date());
        newUser.setPassword(MD5Util.string2MD5(dto.getPassword()));
        newUser.setLastLoginIp(CommonUtil.getIpAddr(request));
        newUser.setUserLevel(0);
        newUser.setStatus(0);
        newUser.setAddTime(new Date());
        newUser.setDeleted(0);
        newUser.setMobile(dto.getPhone());

        //获得微信Openid
        WeiXinSubmitUtil weiXinSubmitController = new WeiXinSubmitUtil();
        Map map = weiXinSubmitController.decodeUserInfo(dto.getCode());
        String openid = map.get("openid").toString();
        newUser.setWeiXinOpenId(openid);
        newUser.setGender(0);
        newUser.setUserLevel(0);
        int i = mapper.addUser(newUser);
        if (i <= 0) {
            //创建失败
            return Result.fail(InfoCode.FAILED, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        DtsUser news = mapper.getUserByPhone(dto.getPhone());
        DtsUserVO vo = new DtsUserVO();
        BeanUtil.copyProperties(news, vo);
        //创建成功并登录(返回saToken和用户)
        StpKit.USER.login(vo.getId());
        SaTokenInfo tokenInfo = StpKit.USER.getTokenInfo();
        Map returnMap = new HashMap();
        returnMap.put("saToken", tokenInfo.tokenValue);
        returnMap.put("user", vo);
        return Result.result(InfoCode.CREATED, InfoCode.MESSAGE_CREATED, returnMap, System.currentTimeMillis());
    }

    @Override
    public Result weiXinLoginByPwd(Map map) {
        //123
        WeiXinSubmitUtil weiXinSubmitController = new WeiXinSubmitUtil();
        Map maps = weiXinSubmitController.decodeUserInfo(map.get("code").toString());
        String openid = maps.get("openid").toString();
        String username = map.get("username").toString();
        String password = map.get("password").toString();
        String s = MD5Util.string2MD5(password);
        DtsUser wxUser = mapper.weiXinLogin(openid, username, s);
        if (wxUser == null) {
            //查无此人
            return Result.fail(InfoCode.QUERY_EMPTY, InfoCode.MESSAGE_QUERY_EMPTY, System.currentTimeMillis());
        }
//        map.put("password", s);
//        wxUser = mapper.weiXinLoginByPwd(map);
//        if (wxUser == null) {
//            //为空(用户名或密码错误)
//            return Result.fail(InfoCode.NAMEORPASSWORD_FAILED, InfoCode.MESSAGE_NAMEORPASSWORD_FAILED, System.currentTimeMillis());
//        }
        //登录成功
        StpKit.USER.login(wxUser.getId());
        SaTokenInfo tokenInfo = StpKit.USER.getTokenInfo();
        DtsUserVO vo = new DtsUserVO();
        BeanUtil.copyProperties(wxUser, vo);
        Map returnMap = new HashMap();

        returnMap.put("saToken", tokenInfo.tokenValue);
        returnMap.put("user", vo);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, returnMap, System.currentTimeMillis());
    }

    @Override
    public Result resetPassword(Map<String, Object> map) {
        //判断验证码是否正确
        String phone = map.get("phone").toString();
        String yzm = map.get("yzm").toString();
        String password = map.get("password").toString();

        String redisYzm = template.opsForValue().get(StorageVariable.PHONE_MESS + phone);
        if (!yzm.equals(redisYzm)) {
            //验证码错误
            return Result.fail(InfoCode.UNPROCESSABLE_ENTITY, InfoCode.MESSAGE_UNPROCESSABLE_ENTITY, System.currentTimeMillis());
        }
        //判断新密码是否与原密码一致
        DtsUser user = mapper.getUserByPhone(phone);
        if (user.getPassword().equals(MD5Util.string2MD5(password))) {
            //一致
            return Result.fail(InfoCode.BAD_REQUEST, InfoCode.MESSAGE_BAD_REQUEST, System.currentTimeMillis());
        }
        //修改
        int res = mapper.resetPassword(phone, MD5Util.string2MD5(password));
        if (res < 0) {
            return Result.fail(InfoCode.FAILED, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, true, System.currentTimeMillis());
    }

    @Override
    public Map<String, Object> getUsersList(UsersDto usersDto) {
        // Redis Key 存储，包含页码和条件
        StringBuilder redisKeyBuilder = new StringBuilder("UsersList");

        // 检查昵称
        if (usersDto.getNickname() != null && !usersDto.getNickname().isEmpty()) {
            redisKeyBuilder.append(":nickname:").append(usersDto.getNickname());
        }

        // 检查手机号
        if (usersDto.getMobile() != null && !usersDto.getMobile().isEmpty()) {
            redisKeyBuilder.append(":mobile:").append(usersDto.getMobile());
        }
        redisKeyBuilder.append(":page:").append(usersDto.getPageNum());
        String redisKey = redisKeyBuilder.toString();
        List<DtsUser> usersList = null;

        // 默认情况下，如果两个条件都为空，仍然添加页码
        // 从 Redis 中获取用户列表和总数
        // 检查 Redis 中是否存在当前页的数据
        if (redisUtil.hasKey(redisKey)) {
            System.out.println("从 Redis 中获取数据");
            usersList = (List<DtsUser>) redisUtil.get(redisKey);
            Map<String, Object> map1 = new HashMap<>();
            // 获取存储的总数

            map1.put("list", usersList);
            map1.put("total", redisUtil.get("UsersList:total")); // 使用从 Redis 获取的总数
            map1.put("pageNum", usersDto.getPageNum());
            map1.put("pageSize", usersDto.getPageSize());
            return map1;
        } else {
            // 开始分页
            Page page = PageHelper.startPage(usersDto.getPageNum(), usersDto.getPageSize());
            usersList = mapper.getUsersList(usersDto);
            Map<String, Object> map = new HashMap<>();
            // 计算总数
//            long total = page.getTotal();

            // 将查询结果放入 Redis，设置过期时间，例如：1小时
            redisUtil.set(redisKey, usersList, 3600);
            redisUtil.set("UsersList:total", mapper.getUsersCount(), 3600);

            map.put("list", page.getResult());
            map.put("total", page.getTotal()); // 使用从数据库计算的总数
            map.put("totalPage", page.getPages());
            map.put("pageNum", page.getPageNum());
            map.put("pageSize", page.getPageSize());
            return map;
        }
    }

    @Override
    public int UpdateStatus(Integer uid) {
        DtsUserAccount userAccountByid = dtsUserAccountMapper.getUserAccountByid(uid);
        if (userAccountByid != null) {
            return mapper.UpdateStatus(uid);
        } else {
            return 0;
        }
    }

    @Override
    public Result weiXinLogin(WeiXinLoginDto dto, HttpServletRequest request) {
        if (dto == null) {
            return Result.fail(InfoCode.BAD_REQUEST, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        //获得openId
        WeiXinSubmitUtil util = new WeiXinSubmitUtil();
        String code = dto.getCode();
        Map maps = util.decodeUserInfo(code);
        Object openid = maps.get("openid");
        if (ObjectUtil.isEmpty(openid)) {
            return Result.fail(InfoCode.BAD_REQUEST, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        //查询是否有此人
        DtsUser user = mapper.weiXinLoginByName(openid.toString());
        if (ObjectUtil.isEmpty(user)) {
            //无
            return Result.fail(InfoCode.QUERY_EMPTY, InfoCode.MESSAGE_QUERY_EMPTY, System.currentTimeMillis());
        }
        StpKit.USER.login(user.getId());
        //获得saToken
        SaTokenInfo tokenInfo = StpKit.USER.getTokenInfo();
        DtsUserVO vo = new DtsUserVO();
        BeanUtil.copyProperties(user, vo);
        Map returnMap = new HashMap();
        returnMap.put("saToken", tokenInfo.tokenValue);
        returnMap.put("user", vo);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, returnMap, System.currentTimeMillis());
    }

    @Override
    public Result userProxy(Object userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Result.fail(InfoCode.BAD_REQUEST, InfoCode.MESSAGE_BAD_REQUEST, System.currentTimeMillis());
        }
        //修改用户代理为3(待审核)
        int res = mapper.updateUserLevel(3, userId);
        if (res == 0) {
            return Result.fail(InfoCode.FAILED, InfoCode.MESSAGE_FAILED, System.currentTimeMillis());
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, 1, System.currentTimeMillis());
    }

    @Override
    public Integer deleteHistory(Integer loginIdAsInt) {
        Integer result = mapper.deleteHistory(loginIdAsInt);
        return result;
    }

    @Override
    public Result collectTrueOrFalse(Map map) {
        int loginIdAsInt = StpKit.USER.getLoginIdAsInt();
        Integer type = Integer.parseInt(map.get("type").toString());
        Integer valueId = Integer.valueOf(map.get("valueId").toString());
        Integer flag = 0;//不收藏
        if (!type.equals(0)) {
            flag = 1;//收藏
        }
        //判断是否收藏过
        Integer res = mapper.findCollect(loginIdAsInt, valueId);
        if (res > 0) {
            //收藏过,仅需要更改deleted
            mapper.collectTrueOrFalse(flag, valueId, loginIdAsInt);
        } else {
            mapper.insertCollect(flag, valueId, loginIdAsInt);
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, flag, System.currentTimeMillis());
    }
}
